package com.algorithm.queue;/*
 *@Author:DOWN
 *@Date:2021/12/25 15:52
 *@Comment:
 */

public class LoopQueueNoSize<E> implements QueueInterface<E> {
    private E[] data;
    int front, tail;

    public LoopQueueNoSize(int capacity) {
        data = (E[]) new Object[capacity+1];
        front = 0;
        tail = 0;
    }

    public LoopQueueNoSize() {
        this(11);
    }

    /**
     * 获取循环队列容量
     * @return int
     */
    public int getCapacity() {
        return data.length-1;
    }

    /**
     * 获取循环队列个数
     *  tail>=front 未循环倒置 tail-front
     *  front>tail  循环倒置  data.length-(front-tail(空的元素))
     * @return int
     */
    @Override
    public int getSize() {
        return this.tail>=this.front?this.tail-this.front:this.data.length-this.front+this.tail;
    }

    /**
     * 判断循环队列是否为空
     * @return boolean
     */
    @Override
    public boolean isEmpty() {
        return this.front == this.tail;
    }

    /**
     * 元素入队
     * @param e Object元素
     */
    @Override
    public void enqueue(E e) {
        if (getSize() == getCapacity()) {
            reSize(getCapacity() * 2);
        }
        this.data[tail] = e;
        this.tail = (this.tail + 1) % this.data.length;
    }

    /**
     * 扩、缩循环队列容量
     * @param capacity + -
     */
    public void reSize(int capacity) {
        int oldSize=getSize();
        E[] newE = (E[]) new Object[capacity+1];
        for (int i = 0; i < getSize(); i++) {
            newE[i] = this.data[(i + front) % this.data.length];
        }
        this.data = newE;
        front = 0;
        tail = oldSize;
    }

    /**
     * 元素出队
     * @return Queue--/E out from queue
     */
    @Override
    public E dequeue() {
        if (isEmpty()) {
            throw new IllegalArgumentException("Cannot dequeue from an empty queue.");
        }
        E old = this.data[this.front];
        this.data[this.front] = null;
        this.front = (this.front + 1) % this.data.length;
        if (getSize() == getCapacity() / 4 && getCapacity() / 2 != 0) {
            reSize(getCapacity() / 2);
        }
        return old;
    }

    /**
     * 获取队首元素
     * @return 元素E
     */
    @Override
    public E getFront() {
        if (isEmpty()) {
            throw new IllegalArgumentException("Cannot dequeue from an empty queue.");
        }
        return this.data[this.front];
    }

    @Override
    public String toString() {
        if (this.data == null) {
            return "null";
        }
        int iMax = tail;
        if (iMax == -1) {
            return "[]";
        }
        StringBuilder b = new StringBuilder();
        b.append("Queue-Front:");
        b.append('[');
        for (int i = 0; i < getSize(); i++) {
            b.append(this.data[(i + front) % this.data.length]);
            if ((i + front + 1) % this.data.length == iMax) {
                return b.append(']').toString();
            }
            b.append(", ");
        }
        return b.toString();
    }

    public static void main(String[] args) {
        LoopQueueNoSize<Integer> arrayQueue = new LoopQueueNoSize<>();
        for (int i = 0; i < 15; i++) {
            arrayQueue.enqueue(i);
            System.out.println(arrayQueue.toString());
            if (i % 3 == 2) {
                arrayQueue.dequeue();
            }
        }
        System.out.println(arrayQueue.toString());
        System.out.println(-1 % 7);
    }
}
